import { getCurrentInstance, reactive, inject, provide } from 'vue'
import type { Node, EventAction } from '@/types/schema'

const RENDERER_CONTEXT_KEY = 'renderer-context'

export interface RendererContext {
  nodes: Record<string, Node>
  registerNode: (node: Node) => void
  unregisterNode: (id: string) => void
  getValue: (id: string, prop: string) => any
}

export function createRendererContext(): RendererContext {
  const nodes = reactive<Record<string, Node>>({})

  return {
    nodes,
    registerNode(node: Node) {
      nodes[node.id] = node
    },
    unregisterNode(id: string) {
      delete nodes[id]
    },
    getValue(id: string, prop: string) {
      return nodes[id]?.props?.[prop]
    }
  }
}

export function provideRendererContext() {
  const context = createRendererContext()
  provide(RENDERER_CONTEXT_KEY, context)
  return context
}

export function useRenderer() {
  const instance = getCurrentInstance()
  if (!instance) {
    throw new Error('useRenderer must be called in setup()')
  }

  // 修改为可选注入，提供默认值
  const context = inject<RendererContext | null>(RENDERER_CONTEXT_KEY, null)

  // 提供默认实现而不是抛出错误
  const defaultContext: RendererContext = {
    nodes: {},
    registerNode: () => {},
    unregisterNode: () => {},
    getValue: () => undefined
  }

  const safeContext = context || defaultContext

  const registerNode = (node: Node) => {
    safeContext.registerNode(node)
  }

  const getContextValue = (id: string, prop: string) => {
    return safeContext.getValue(id, prop)
  }

  const replaceVariables = (str: string, currentId: string): string => {
    return str.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
      const trimmed = expr.trim()
      if (trimmed === 'this') return ''
      if (trimmed.startsWith('this.')) {
        const prop = trimmed.slice(5)
        return safeContext.getValue(currentId, prop) || ''
      }
      const [id, prop] = trimmed.split('.')
      return safeContext.getValue(id, prop) || ''
    })
  }

  const executeEventActions = (actions: EventAction[], nodeId: string) => {
    for (const action of actions) {
      if (action.type === 'alert') {
        let message = action.params.message || ''
        message = replaceVariables(message, nodeId)
        alert(message)
      }
    }
  }

  return {
    registerNode,
    getContextValue,
    executeEventActions
  }
}
